package com.clstu.sparseArr;

import java.io.*;

/**   针对的是方形的二维数组,暂不针对不整齐的二维数组
 * 稀疏数组的使用(应用场景,在大多数元素相同的情况下压缩空间,分3列[ rows cols val ]第0个元素保存源二维数组的大小和不同元素的个数)
 * 二维数组-->稀疏数组
 * 稀疏数组-->二维数组
 */
public class SparseArr {
    public static void main(String[] args) throws IOException {
        //假设数组是一个11*11的五子棋棋盘 1表示黑子 2表示白子 0表示空(占绝大部分)
        int[][] arr = new int[11][11];
        //假设棋盘上只有如下几个棋子
        arr[2][3]=1;
        arr[3][4]=2;
        arr[2][6]=1;
        //输出二维数组
        System.out.println("原二维数组");
        for (int[] ints : arr) {
            for (int i : ints) {
                System.out.print(i+"\t");
            }
            System.out.println();
        }
        //转成稀疏数组,(二维数组--->稀疏数组)
        // 1.遍历全部统计所有的非0的个数
        int count = 0;
        for (int[] ints : arr) {
            for (int i : ints) {
                if(i!=0) count++;
            }
        }
        //2.new 稀疏数组
        int[][] sparseArr = new int[count+1][3];
        //3.初始化(保存源二维数组的 行数 列数 非零值个数)
        sparseArr[0][0]=arr.length;
        sparseArr[0][1]=arr[0].length;
        sparseArr[0][2]=count;
        //4.给稀疏数组赋值,循环
        count=0;
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                if(arr[i][j]!=0){
                    count++;
                    sparseArr[count][0] = i;//行
                    sparseArr[count][1] = j;//列
                    sparseArr[count][2] = arr[i][j];//值
                }
            }
        }
        //查看稀疏数组
        System.out.println("二维数组--->稀疏数组");
        for (int[] ints : sparseArr) {
            for (int i : ints) {
                System.out.print(i+"\t");
            }
            System.out.println();
        }
        //存盘,保存到文件中,下次运行程序时可以继续上局
        save(sparseArr);

        //从磁盘读取
        sparseArr = goOn();
        System.out.println("io---->稀疏数组");
        for (int[] ints : sparseArr) {
            for (int i : ints) {
                System.out.print(i+"\t");
            }
            System.out.println();
        }

        //稀疏数组 ---> 二维数组
        //1.根据稀疏数组第0个元素new 二维数组
        int[][] arr2 = new int[sparseArr[0][0]][sparseArr[0][1]];
        //2.遍历赋值
        for (int i = 1; i < sparseArr.length; i++) {//这里判断条件是 sparseArr.length(不然少一个恢复不到)
            arr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
        }
        //查看转换回来的二维数组
        System.out.println("稀疏数组--->二维数组");
        for (int[] ints : arr2) {
            for (int i : ints) {
                System.out.print(i+"\t");
            }
            System.out.println();
        }
    }

    //编写方法实现存盘需上局功能.利用文件io
    public static void save(int[][] sparseArr) throws IOException {
        //节点转换流,用字符流写入
        //如果打开的文件不存在就自动创建
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("src\\sArr.txt")));
        //循环存入
        for (int[] ints : sparseArr) {
            bw.write(ints[0]+" "+ints[1]+" "+ints[2]);
            bw.newLine();
        }
        //关闭资源(不关闭不保存到磁盘中!!)
        bw.close();
    }

    //编写方法实现 从文件读取数据 --(转换)--> 稀疏数组 实现续上局功能
    public static int[][] goOn() throws IOException {
        //用节点转换流读取数据,字符流读取
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("src\\sArr.txt")));
        //创建稀疏数组
        int[][] sArr = null;
        //循环取出,写入稀疏数组
        int count = 0;
        String line = "";
        while ((line=br.readLine())!=null){
            String[] s = line.split(" ");
            if(count==0) {
                //初始化数组
                sArr = new int[Integer.parseInt(s[2])+1 ][3];
            }
            sArr[count][0]=Integer.parseInt(s[0]);
            sArr[count][1]=Integer.parseInt(s[1]);
            sArr[count][2]=Integer.parseInt(s[2]);
            count++;
        }
        return sArr;
    }
}
